function normalizeName(name) {
  if (typeof name !== 'string') {
    name = String(name);
  }
  if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name) || name === '') {
    throw new TypeError('Invalid character in header field name');
  }
  return name.toLowerCase();
}
function makeIterator(array) {
  return {
    next: function () {
      let value = array.shift();
      return { done: value === undefined, value: value };
    }
  };
}
class Headers {
  constructor(headers) {
    this._map = {};
    if (headers instanceof Headers) {
      headers.forEach((value, name) => {
        this.append(name, value);
      });
    }
    else if (Array.isArray(headers)) {
      headers.forEach(header => {
        this.append(header[0], header[1]);
      });
    }
    else {
      if (headers && typeof headers === 'object') {
        Object.getOwnPropertyNames(headers).forEach((name) => {
          this.append(name, headers[name]);
        });
      }
    }
  }
  append(name, value) {
    name = normalizeName(name);
    let oldValue = this._map[name];
    value = oldValue ? oldValue + ',' + value : value;
    this._map[name] = value;
  }
  delete(name) {
    delete this._map[normalizeName(name)];
  }
  get(name) {
    return this._map[normalizeName(name)];
  }
  has(name) {
    return this._map.hasOwnProperty(normalizeName(name));
  }
  set(name, value) {
    this._map[normalizeName(name)] = value;
  }
  keys() {
    return makeIterator(Object.keys(this._map));
  }
  values() {
    return makeIterator(Object.values(this._map));
  }
  entries() {
    let items = [];
    this.forEach((value, name) => {
      items.push([name, value]);
    });
    return makeIterator(items);
  }
  forEach(callback, thisArg) {
    for (const name in this._map) {
      if (this._map.hasOwnProperty(name)) {
        callback.call(thisArg, this._map[name], name, this._map);
      }
    }
  }
  [Symbol.iterator]() {
    return this.entries;
  }
  valueOf() {
    return this._map;
  }
}

module.exports = Headers;